using System;
using System.Linq;
using System.Text;
using DevExpress.Xpo;
using DevExpress.ExpressApp;
using System.ComponentModel;
using DevExpress.ExpressApp.DC;
using DevExpress.Data.Filtering;
using DevExpress.Persistent.Base;
using System.Collections.Generic;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.ExpressApp.ConditionalAppearance;
using DomainComponents.Common;

namespace DomainComponents.XCRM
{
    public class SaleBaseValidationRules
    {
        public const string NameIsRequired = "SaleBaseNameIsRequired";
        public const string PotentialCustomerIsRequired = "PotentialCustomerIsRequired";
        public const string DiscountIsGreaterThanOrEqualZero = "SaleBaseDiscountIsGreaterThanOrEqualZero";
        public const string DiscountPercentIn0_100Range = "SaleBaseDiscountPercentIn0_100Range";
    }

    public enum ShippingMethod
    {
        None = 0,
        Airborne = 1,
        DHL = 2,
        FedEx = 3,
        UPS = 4,
        PostalMail = 5,
        FullLoad = 6,
        WillCall = 7
    }

    [DomainComponent]
    [Appearance("Disable Amount", TargetItems = "Amount", Criteria = "", Enabled = false)]
    [XafDisplayName("Sale Base")]
    public interface ISaleBase /*: INotable, IActivityTarget */{
        [RuleRequiredField(SaleBaseValidationRules.NameIsRequired, DefaultContexts.Save)]
        string Name { get; set; }

        [RuleRequiredField(SaleBaseValidationRules.PotentialCustomerIsRequired, DefaultContexts.Save)]
        ICustomer PotentialCustomer { get; set; }

        decimal Amount { get; set; }

        [DevExpress.ExpressApp.DC.Aggregated]
        IList<ISaleItem> SaleItems { get; }

        [VisibleInListView(false)]
        IDCUser Owner { get; set; }

        [RuleValueComparison(SaleBaseValidationRules.DiscountIsGreaterThanOrEqualZero, DefaultContexts.Save, ValueComparisonType.GreaterThanOrEqual, 0)]
        [ImmediatePostData]
        [VisibleInListView(false)]
        decimal Discount { get; set; }

        [RuleRange(SaleBaseValidationRules.DiscountPercentIn0_100Range, DefaultContexts.Save, 0, 100)]
        [ImmediatePostData]
        [ModelDefault("DisplayFormat", "{0:N}")]
        [ModelDefault("EditMask", "N")]
        [VisibleInListView(false)]
        decimal DiscountPercent { get; set; }

        [Calculated("SaleItems.Sum(Amount)")]
        [VisibleInListView(false)]
        decimal DetailAmount { get; }

        [VisibleInListView(false)]
        string ID { get; set; }

        [VisibleInDetailView(false), VisibleInListView(false)]
        DateTime CreatedOn { get; set; }

        void UpdateAmount();

        void Copy(ISaleBase target);
    }

    [DomainComponent]
    [NonPersistentDc]
    public interface IGenericAddressableSale
    {
        [DevExpress.ExpressApp.DC.Aggregated]
        [VisibleInListView(false)]
        IBaseAddress BillToAddress { get; set; }

        [DevExpress.ExpressApp.DC.Aggregated]
        [VisibleInListView(false)]
        IBaseAddress ShipToAddress { get; set; }

        [VisibleInListView(false)]
        DateTime DeliveryDate { get; set; }

        [VisibleInListView(false)]
        ShippingMethod ShippingMethod { get; set; }

        [CreateInstance]
        IBaseAddress CreateAddress();
        void Copy(IGenericAddressableSale target);
    }


    [DomainLogic(typeof(IGenericAddressableSale))]
    public class GenericAddressableSaleLogic
    {
        public static void AfterConstruction(IGenericAddressableSale sale, IObjectSpace os)
        {
            if (sale.BillToAddress == null)
            {
                sale.BillToAddress = sale.CreateAddress();
            }
            if (sale.ShipToAddress == null)
            {
                sale.ShipToAddress = sale.CreateAddress();
            }
        }
        public void Copy(IGenericAddressableSale source, IObjectSpace os, IGenericAddressableSale target)
        {
            if (target != null)
            {
                target.BillToAddress = source.BillToAddress;
                target.ShipToAddress = source.ShipToAddress;
                target.ShippingMethod = source.ShippingMethod;
                target.DeliveryDate = source.DeliveryDate;
            }
        }
    }

    [DomainLogic(typeof(ISaleBase))]
    public class SaleBaseLogic
    {
        public void Copy(ISaleBase source, IObjectSpace os, ISaleBase target)
        {
            //rewrite with Cloner - S35833
            target.Discount = source.Discount;
            target.DiscountPercent = source.DiscountPercent;
            target.Name = source.Name;
            target.Owner = source.Owner;
            target.PotentialCustomer = source.PotentialCustomer;

            foreach (ISaleItem saleItem in source.SaleItems)
            {
                ISaleItem saleItemNew = os.CreateObject<ISaleItem>();
                saleItemNew.Discount = saleItem.Discount;
                saleItemNew.Product = saleItem.Product;
                saleItemNew.Quantity = saleItem.Quantity;
                saleItemNew.UpdateAmount();

                target.SaleItems.Add(saleItemNew);
            }
            target.UpdateAmount();

            if (target is IOpportunityTarget)
            {
                if (source is IOpportunity)
                {
                    ((IOpportunityTarget)target).SourceOpportunity = (IOpportunity)source; //TODO
                }
                else if (source is IOpportunityTarget)
                {
                    ((IOpportunityTarget)target).SourceOpportunity = ((IOpportunityTarget)source).SourceOpportunity;
                }
            }
            if (source is IGenericAddressableSale)
            {
                ((IGenericAddressableSale)source).Copy(target as IGenericAddressableSale); //TODO
            }
        }

        public static void AfterConstruction(ISaleBase saleBase, IObjectSpace os)
        {
            saleBase.CreatedOn = DateTime.Now;
        }
        public static void UpdateAmount(ISaleBase saleBase)
        {
            saleBase.Amount = saleBase.DetailAmount - saleBase.Discount -
                (saleBase.DetailAmount - saleBase.Discount) * saleBase.DiscountPercent / 100;
        }

        public static void AfterChange_Discount(ISaleBase saleBase)
        {
            saleBase.UpdateAmount();
        }

        public static void AfterChange_DiscountPercent(ISaleBase saleBase)
        {
            saleBase.UpdateAmount();
        }
    }

    //[DefaultClassOptions]
    ////[ImageName("BO_Contact")]
    ////[DefaultProperty("DisplayMemberNameForLookupEditorsOfThisType")]
    ////[DefaultListViewOptions(MasterDetailMode.ListViewOnly, false, NewItemRowPosition.None)]
    ////[Persistent("DatabaseTableName")]
    //// Specify more UI options using a declarative approach (http://documentation.devexpress.com/#Xaf/CustomDocument2701).
    //public class ISaleBase : BaseObject
    //{ // Inherit from a different class to provide a custom primary key, concurrency and deletion behavior, etc. (http://documentation.devexpress.com/#Xaf/CustomDocument3146).
    //    public ISaleBase(Session session)
    //        : base(session)
    //    {
    //    }
    //    public override void AfterConstruction()
    //    {
    //        base.AfterConstruction();
    //        // Place your initialization code here (http://documentation.devexpress.com/#Xaf/CustomDocument2834).
    //    }
    //    //private string _PersistentProperty;
    //    //[XafDisplayName("My display name"), ToolTip("My hint message")]
    //    //[ModelDefault("EditMask", "(000)-00"), Index(0), VisibleInListView(false)]
    //    //[Persistent("DatabaseColumnName"), RuleRequiredField(DefaultContexts.Save)]
    //    //public string PersistentProperty {
    //    //    get { return _PersistentProperty; }
    //    //    set { SetPropertyValue("PersistentProperty", ref _PersistentProperty, value); }
    //    //}

    //    //[Action(Caption = "My UI Action", ConfirmationMessage = "Are you sure?", ImageName = "Attention", AutoCommit = true)]
    //    //public void ActionMethod() {
    //    //    // Trigger a custom business logic for the current record in the UI (http://documentation.devexpress.com/#Xaf/CustomDocument2619).
    //    //    this.PersistentProperty = "Paid";
    //    //}
    //}
}
